package timetabling;

import generalEvolutionaryAlgorithm.EABlackBoxFunction;
import generalEvolutionaryAlgorithm.EAInstance;
import generalEvolutionaryAlgorithm.EAInstanceGenerator;

import java.util.ArrayList;

import common.RandomGenerator;

public class TimetablingGeneratorGreedy  implements EAInstanceGenerator {
	private boolean[][] studentAttendsEvent;
	private boolean[][] eventCanTakePartInRoom;
	private int events, rooms;
	public TimetablingGeneratorGreedy(boolean[][] studentAttendsEvent, boolean[][] eventCanTakePartInRoom) {
		this.studentAttendsEvent = studentAttendsEvent;
		this.eventCanTakePartInRoom = eventCanTakePartInRoom;
		events = this.studentAttendsEvent[0].length;
		rooms = this.eventCanTakePartInRoom[0].length;
	}

	@Override
	public EAInstance generateInstance(EABlackBoxFunction function) {
		int timeForEvent[] = new int[events];
		for(int i = 0; i < events; i++){
			timeForEvent[i] = -1;
		}
		int roomForEvent[] = new int[events];
		for(int i = 0; i < events; i++){
			roomForEvent[i] = -1;
		}
		int timesUsed[] = new int[rooms];
		int days = TimetablingConstants.DAYS;
		int hours = TimetablingConstants.HOURS;
		int spots = days * hours;
		while(true){
			int minimalRoomsAndTimes = rooms * spots;
			ArrayList<Integer> toChoose = new ArrayList<Integer>();
			for(int event = 0; event < events; event++){
				if(timeForEvent[event] == -1){
					int possiblePositions = 0;
					for(int room = 0; room < rooms; ++room){
						if(eventCanTakePartInRoom[event][room]){
							possiblePositions += spots - timesUsed[room];
						}
					}
					if(possiblePositions > 0){
						if(possiblePositions < minimalRoomsAndTimes){
							toChoose.clear();
							minimalRoomsAndTimes = possiblePositions;
						}
						if(possiblePositions == minimalRoomsAndTimes){
							toChoose.add(event);
						}
					}
				}
			}
			if(toChoose.isEmpty()){
				break;
			}
			int useEvent = toChoose.get(RandomGenerator.getInt(toChoose.size()));
			int randomAssign = RandomGenerator.getInt(minimalRoomsAndTimes);
			for(int room = 0; room < rooms; ++room){
				if(eventCanTakePartInRoom[useEvent][room]){
					randomAssign -= spots - timesUsed[room];
					if(randomAssign < 0){
						roomForEvent[useEvent] = room;
						timeForEvent[useEvent] = timesUsed[room]++;
						break;
					}
				}
			}
		}
		return new TimetablingInstance(function, timeForEvent, roomForEvent, rooms);
	}

}
